#ifndef XLCOMM_NET_TCPSERVER_H_
#define XLCOMM_NET_TCPSERVER_H_

#include <atomic>
#include <map>
#include <memory>
#include <string>

#include "xlcomm/define.h"
#include "xlcomm/net/callbacks.h"
#include "xlcomm/net/detail/acceptor.h"
#include "xlcomm/net/detail/event_loop_thread_pool.h"
#include "xlcomm/net/event_loop.h"
#include "xlcomm/net/tcp_connection.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {
namespace net {

class Acceptor;
class EventLoopThreadPool;

// TCP服务端
class XLCOMM_API TcpServer : noncopyable {
 public:
  using ThreadInitCallback = std::function<void(EventLoop*)>;

  enum Option {
    kNotReusePort,
    kReusePort,
  };

  TcpServer(EventLoop* loop, const InetAddress& listen_addr,
            const std::string& name, Option option = kNotReusePort);
  ~TcpServer();

  // 启动Tcp服务。可以多次调用，但只启动一次（线程安全）
  // @param thread_num
  // 0: 所有I/O在loop主线程，不创建新线程
  // 1: 所有I/O在单独创建的新线程
  // N: 创建N个线程的线程池, 新连接循环分配到这N个线程中
  void Start(int thread_num = 0,
             const ThreadInitCallback& cb = ThreadInitCallback());

  // 注册连接建立后的回调（非线程安全）
  void set_connect_callback(const ConnectCallback& cb) {
    connect_callback_ = cb;
  }
  // 注册连接断开后的回调（非线程安全）
  void set_disconnect_callback(const DisconnectCallback& cb) {
    disconnect_callback_ = cb;
  }
  // 注册消息读出后的回调（非线程安全）
  void set_message_callback(const MessageCallback& cb) {
    message_callback_ = cb;
  }
  // 注册缓冲区消息写完后的回调（非线程安全）
  // 低流量应用可以不用关心这个事件
  void set_write_complete_callback(const WriteCompleteCallback& cb) {
    write_complete_callback_ = cb;
  }

  const std::string& ip_port() const { return ip_port_; }
  const std::string& name() const { return name_; }
  // 获取loop，可以用于其他TcpServer或TcpClient
  EventLoop* loop() const { return loop_; }
  // 获取loop线程池，将来如果有需要 可以多个TcpServer共享loop线程池
  // Start之后才有效
  std::shared_ptr<EventLoopThreadPool> thread_pool() { return thread_pool_; }

 private:
  using ConnectionMap = std::map<std::string, TcpConnectionPtr>;

  // 新连接处理函数（在loop_线程里运行）
  void NewConnection(int sockfd, const InetAddress& peer_addr);
  // 移除连接（线程安全）
  void RemoveConnection(const TcpConnectionPtr& conn);
  // 在loop线程移除连接（在loop_线程里运行）
  void RemoveConnectionInLoop(const TcpConnectionPtr& conn);

  EventLoop* loop_;
  std::string ip_port_;
  std::string name_;
  uint64_t conn_id_;
  std::unique_ptr<Acceptor> acceptor_;
  std::shared_ptr<EventLoopThreadPool> thread_pool_;
  ConnectionMap connections_;
  std::atomic<int> started_;

  ConnectCallback connect_callback_;
  DisconnectCallback disconnect_callback_;
  MessageCallback message_callback_;
  WriteCompleteCallback write_complete_callback_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_TCPSERVER_H_